<?php

namespace App\Service\Authorization;

use App\Models\users\UsersModel;
use App\Models\users\UsersSettingModel;
use App\Service\users\UsersService;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use lxs\config\BaseStatic;
use lxs\tools\AuthToken;
use lxs\tools\CacheRedis;
use lxs\tools\Tools;
use lxs\wechat\OpenInterface;

class LoginService extends BaseStatic
{

    /**
     * 网站扫码登录
     * @param $code string 扫码返回的code
     * @param $state string 扫码返回的state
     * @param $appid string 微信公众号appid
     * @param $secret string 微信公众号appsecret
     * @return array
     */
    public function wechatQrcodeHandle(string $code, string $state, string $appid, string $secret): array
    {
        $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
        $response = Http::get($url);

        if ( isset($response['access_token']) && isset($response['openid']) && isset($response['unionid']) ) {

            $access_token = $response['access_token'];
            $openid = $response['openid'];
            $unionid = $response['unionid'];

            $userInfo = UsersModel::where('unionid', $unionid)->first();
            $uid = $userInfo->id ?? 0;

            if ( !$uid ) {
                $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}";
                $response = Http::get($url);
                if ( isset($response['nickname']) && isset($response['headimgurl']) ) {
                    $data['unique_id'] = Tools::getUniqueMobile();
                    $data['openid'] = $openid;
                    $data['unionid'] = $unionid;
                    $data['nickname'] = $response['nickname'];
                    $data['avatar'] = $response['headimgurl'];
                    $data['mobile'] = '';
                    $data['password'] = '';
                    $uid = $this->registerProcess($data);
                } else {
                    return self::serviceReturn(503, '微信登录失败');
                }
            }

            $auth = new AuthToken();
            $token = $auth->createToken($uid, 'web');
            return self::serviceReturn(200, '登录成功', $token);

        }

        return self::serviceReturn(504, '微信登录失败');
    }


    /**
     * 小程序注册表单提交
     */
    public function registerSubmit(array $data): array
    {
        $key = 'register_' . $data['mobile'];
        if (CacheRedis::instance()->limit($key, 5) === false) {
            return self::serviceReturn(502, '操作过于频繁');
        }

        try {
            DB::beginTransaction();

            $data['unique_id'] = Tools::getUniqueMobile();

            $getWechatInfo = (new OpenInterface())->getOpenId($data['code']);

            $data['openid'] = $getWechatInfo['openid'];

            $data['unionid'] = $getWechatInfo['unionid'];

            $data['password'] = hash_hmac('sha256', $data['password'], config('app.key'));

            $uid = $this->registerProcess($data);

            DB::commit();
            return self::serviceReturn(200, '注册成功', ['uid' => $uid]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('注册失败：' . $e->getMessage() . $e->getFile() . $e->getLine());
            return self::serviceReturn(500, '注册失败');
        }
    }


    /**
     * 小程序注册处理
     */
    private function registerProcess($data): int
    {

        $userInfo = UsersModel::where('unionid', $data['unionid'])->first();
        if ($userInfo) {
            $userInfo->openid = $data['openid'] ?? '';
            $userInfo->unionid = $data['unionid'] ?? '';
            $userInfo->nickname = $data['nickname'];
            $userInfo->avatar = $data['avatar'];
            $userInfo->mobile = $data['mobile'];
            $userInfo->password = $data['password'];
            $userInfo->save();
        } else {
            $userInfo = new UsersModel();
            $userInfo->unique_id = $data['unique_id'];
            $userInfo->openid = $data['openid'] ?? '';
            $userInfo->unionid = $data['unionid'] ?? '';
            $userInfo->pid = $data['pid'] ?? 0;
            $userInfo->nickname = $data['nickname'];
            $userInfo->avatar = $data['avatar'];
            $userInfo->mobile = $data['mobile'];
            $userInfo->password = $data['password'];
            $userInfo->create_time = time();
            $userInfo->save();
            UsersSettingModel::create(['uid' => $userInfo->id]);
        }
        return $userInfo->id;
    }


    /**
     * 小程序密码登录表单提交
     * @param $mobile number 手机号
     * @param $password string 密码
     * @param $code string 小程序授权码
     * @param $type string 登录类型 wechat：微信登录 web：网站登录
     * @return array
     */
    public function passwordLoginSubmit($mobile, string $password, string $code, string $type): array
    {
        $key = 'password_login_' . $mobile;
        if (CacheRedis::instance()->limit($key, 5) === false) {
            return self::serviceReturn(500, '密码错误次数过多，请稍后再试');
        }

        $result = $this->isUserExist($mobile, $code);
        if ($result['code'] != 200) {
            return self::serviceReturn($result['code'], $result['message']);
        } else {
            $user_list = $result['data'];
        }

        if ($user_list) {
            if (hash_hmac('sha256', $password, config('app.key')) == $user_list['password']) {
                $auth = new AuthToken();
                $token = $auth->createToken($user_list['id'], $type);
                if ($user_list['is_cancel'] == 1) {
                    UsersModel::where('id', $user_list['id'])->update(['is_cancel' => 0]);
                }
                return self::serviceReturn(200, '登录成功', $token);
            }
            return self::serviceReturn(7, '密码不正确');
        }
        return self::serviceReturn(7, '密码不正确');
    }


    /**
     * 小程序验证码登录表单提交
     * @param $mobile number 手机号
     * @param $code string 验证码
     * @param $type string 登录类型 wechat：微信登录 web：网站登录
     * @return array
     */
    public function captchaLoginSubmit($mobile, string $code, string $type='wechat'): array
    {
        $key = 'captcha_login_' . $mobile;
        if (CacheRedis::instance()->limit($key, 5) === false) {
            return self::serviceReturn(500, '操作过于频繁');
        }

        $result = $this->isUserExist($mobile, $code);
        if ($result['code'] != 200) {
            return self::serviceReturn($result['code'], $result['message']);
        } else {
            $user_list = $result['data'];
        }

        if ($user_list) {
            $auth = new AuthToken();
            $token = $auth->createToken($user_list['id'], $type);
            if ($user_list['is_cancel'] == 1) {
                UsersModel::where('id', $user_list['id'])->update(['is_cancel' => 0]);
            }
            return self::serviceReturn(200, '登录成功', $token);
        }
        return self::serviceReturn(7, '表单提交错误');
    }


    /**
     * 判断用户是否存在
     * @param $mobile number 手机号
     * @param $code string 微信code
     */
    public function isUserExist($mobile, string $code=''): array
    {
        $user_list = UsersService::instance()->getUserInfoByMobile($mobile);
        if (!$user_list) {
            return self::serviceReturn(105, '请注册');
        }

        $user_cancel_time = Tools::Config('USER.cancel_time');
        $days = $user_cancel_time * 24 * 60 * 60;
        if ( $user_list->is_cancel == 1 && time() > ($user_list->cancel_time + $days) ) {
            return self::serviceReturn(106, '该账号已注销');
        }

        if ($code) {
            $result = (new OpenInterface())->getOpenId($code);
            if ($result['openid'] != '' && $result['unionid'] != '') {
                UsersModel::where('id', $user_list->id)->update([
                    'openid' => $result['openid'],
                    'unionid' => $result['unionid']
                ]);
            }
        }

        return self::serviceReturn(200, '查询成功', $user_list->toArray());
    }

}
